#===============================================================================
# Koro Business Environment
# Copyright (C) 2008  Antonio Corroppoli
#
#This file is part of Koro BE.
# 
# Koro BE is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# Koro BE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Koro BE; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#===============================================================================
""" kernel.db.gBsddb.py : this module use bsddb to manage data """
#TODO:aggiungere data,ora e utente in gTrashItem
import os.path
import bsddb
import datetime
import cPickle
import zlib
from gap.gLocalize import _
import gap.gException as gException

##absolute path to Berkeley DB files
#TODO: aggiungerlo come parametro in setting. e' il path di installazione
import os
TRASH_PATH = os.path.normpath(os.environ['HOME'])


class gTrash(object):
    def __init__(self): raise
    def put(*args,**kwargs):
        pass
    def remove(*args,**kwargs):
        pass
    def clear(*args,**kwargs):
        pass
    def find(*args,**kwargs):
        pass

class gTrashItem(object):
    """Definisce la struttura logica dei record cancellati."""
    def __init__(self,data=None):
        self.__data=[]
        if isinstance(data,basestring):
            self.__data = cPickle.loads(data)
            assert isinstance(self.__data,list)
        elif data is None:
            pass
        else:
            raise

    def update(self,data):
        assert isinstance(data,dict)
        import time
        data['datetime']=time.time()        
        self.__data.append(data)
        del time
        return cPickle.dumps(self.__data)

    def remove(self,data):
        assert isinstance(data,dict)
        self.__data.remove(data)
        return cPickle.dumps(self.__data)

    def get(self):
        return self.__data
    

class gBsdTrash(gTrash):
    _NAME = ".trash"
    _PATH = os.path.normpath(os.path.join(TRASH_PATH,_NAME))
    @staticmethod
    def put(srcCode,data):
        print 'gBsdTrash.put'
        tpath= gBsdTrash._PATH
        if not os.path.isabs(tpath):
            raise
        trash=bsddb.hashopen(tpath,'c')
        key=str(srcCode)
        if key in trash:
            trash[key]=zlib.compress(gTrashItem(zlib.decompress(trash[key])).update(data))
        else:
            trash[key]=zlib.compress(gTrashItem().update(data))
        trash.close()
    @staticmethod    
    def remove(srcCode,data):
        tpath= gBsdTrash._PATH
        if not os.path.isabs(tpath):
            raise
        trash=bsddb.hashopen(tpath,'w')
        key=str(srcCode)
        if key in trash:
            trash[key]=zlib.compress(gTrashItem(zlib.decompress(trash[key])).remove(data))
        else:
            raise
        trash.close()
    @staticmethod    
    def clear(srcCode=None):
        tpath= gBsdTrash._PATH
        if not os.path.isabs(tpath):
            raise
        trash=bsddb.hashopen(tpath,'w')
        if srcCode is None:
            trash.clear()
            trash.close()
            return
        key=str(srcCode)
        if key in trash:
            del trash[key]
        else:
            raise
        trash.close()
    @staticmethod    
    def find(srcCode):
        """Restituisce la lista dei record con codice srcCode eliminati."""
        tpath= gBsdTrash._PATH
        if not os.path.isabs(tpath):
            raise
        trash=bsddb.hashopen(tpath,'r')
        key=str(srcCode)
        hit=None
        if key in trash:
            hit=gTrashItem(zlib.decompress(trash[key])).get()
        trash.close()
        return hit
